// 《围棋》作者版权所有。版权所有。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package syntax

// ---------------------------------------------------------------
// Nodes 

type Node interface {
	// Pos（）返回与节点关联的位置，如下所示：
	// 1）表示终端语法产品
	// （名称、基本信息等）的节点位置是相应产品
	// 在源代码中。
	// 2）代表非终端产品
	// （IndexExpr、IfStmt等）的节点的位置是与该产品唯一相关的令牌
	// 的位置；通常最左边的一个
	// （“['代表IndexExpr，'如果'代表IfStmt等）
	Pos() Pos
	aNode()
}

type node struct {
	// /由于尚未使用
	// /doc*注释
	pos Pos
}

func (n *node) Pos() Pos { return n.pos }
func (*node) aNode()     {}

// ---------------------------------------------------------------
// /文件

// /包PkgName；DeclList[0]，DeclList[1]。。。
type File struct {
	Pragma   Pragma
	PkgName  *Name
	DeclList []Decl
	EOF      Pos
	node
}

// ---------------------------------------------------------------
// 声明

type (
	Decl interface {
		Node
		aDecl()
	}

	// 路径
	// 本地PKGNAME路径
	ImportDecl struct {
		Group        *Group // nil表示不属于一个组
		Pragma       Pragma
		LocalPkgName *Name     // 包括“；nil表示不存在
		Path         *BasicLit // 路径。糟糕的| |路。种类==StringLit；nil表示没有路径
		decl
	}

	// 名称列表
	// 名称列表=值
	// 名称列表类型=值
	ConstDecl struct {
		Group    *Group // nil表示不属于组
		Pragma   Pragma
		NameList []*Name
		Type     Expr // nil表示没有类型
		Values   Expr // nil表示没有值
		decl
	}

	// 名称类型
	TypeDecl struct {
		Group      *Group // nil表示不属于组
		Pragma     Pragma
		Name       *Name
		Alias      bool
		Type       Expr
		decl
	}

	// 名称列表类型
	// 名称列表类型=值
	// 名称列表=值
	VarDecl struct {
		Group    *Group // nil表示不属于组
		Pragma   Pragma
		NameList []*Name
		Type     Expr // nil表示没有类型
		Values   Expr // nil表示没有值
		decl
	}

	// 函数名称类型{Body}
	// 函数名称类型
	// 函数接收方名称类型{Body}
	// func Receiver Name Type 
	FuncDecl struct {
		Pragma     Pragma
		Recv       *Field // nil表示常规函数
		Name       *Name
		TParamList []*Field // nil表示没有类型参数
		Type       *FuncType
		Body       *BlockStmt // nil表示没有Body（正向声明）
		decl
	}
)

type decl struct{ node }

func (*decl) aDecl() {}

// 属于同一组的所有声明都指向同一组节点。
type Group struct {
	_ int // 不为空，因此我们保证使用不同的组实例
}

// ----------------------------------------------------------------------------------------
// 表达式

func NewName(pos Pos, value string) *Name {
	n := new(Name)
	n.pos = pos
	n.Value = value
	return n
}

type (
	Expr interface {
		Node
		aExpr()
	}

	// 无法正确解析
	// 且无法提供更好节点的表达式的占位符。
	BadExpr struct {
		expr
	}

	// 值
	Name struct {
		Value string
		expr
	}

	// 值
	BasicLit struct {
		Value string
		Kind  LitKind
		Bad   bool // true表示文字值有语法错误
		expr
	}

	// 类型{ElemList[0]，ElemList[1]，…}
	CompositeLit struct {
		Type     Expr // nil表示没有文字类型
		ElemList []Expr
		NKeys    int // 带键的元素数
		Rbrace   Pos
		expr
	}

	// 键：值
	KeyValueExpr struct {
		Key, Value Expr
		expr
	}

	// 函数类型{Body}
	FuncLit struct {
		Type *FuncType
		Body *BlockStmt
		expr
	}

	// （X）
	ParenExpr struct {
		X Expr
		expr
	}

	// X.Sel 
	SelectorExpr struct {
		X   Expr
		Sel *Name
		expr
	}

	// X[索引]
	// X[T1，T2，]（Ti=Index.（*ListExpr）。ElemList[i]）
	IndexExpr struct {
		X     Expr
		Index Expr
		expr
	}

	// X[Index[0]：Index[1]：Index[2]]
	SliceExpr struct {
		X     Expr
		Index [3]Expr
		// Full表示这是一个简单的还是完整的切片表达式。
		// 在有效的AST中，这相当于索引[2]！=无
		// TODO（mdempsky）：当缺少索引[2]时，只需要报告“3索引
		// string切片”错误。
		Full bool
		expr
	}

	// X.（Type）
	AssertExpr struct {
		X    Expr
		Type Expr
		expr
	}

	// X.（Type）
	// Lhs:=X.（Type）
	TypeSwitchGuard struct {
		Lhs *Name // nil表示没有Lhs:=
		X   Expr  // X.（Type）
		expr
	}

	Operation struct {
		Op   Operator
		X, Y Expr // Y==nil表示一元表达式
		expr
	}

	CallExpr struct {
		Fun     Expr
		ArgList []Expr // nil表示没有参数
		HasDots bool   // 最后一个参数后跟。。。
		expr
	}

	// ElemList[0]，ElemList[1]。。。ABCFDG 
	ListExpr struct {
		ElemList []Expr
		expr
	}

	ArrayType struct {
		Len  Expr // nil表示Len是。。。
		Elem Expr
		expr
	}

	// /[]元素
	SliceType struct {
		Elem Expr
		expr
	}

	// /。。。Elem 
	DotsType struct {
		Elem Expr
		expr
	}

	// struct{FieldList[0]标记列表[0]；FieldList[1]标记列表[1]；…}
	StructType struct {
		FieldList []*Field
		TagList   []*BasicLit // i>=len（标记列表）| |标记列表[i]==nil表示字段i没有标记
		expr
	}

	// Name Type 
	// Type 
	Field struct {
		Name *Name // nil表示匿名字段/参数（结构/参数），或嵌入式元素（接口）
		Type Expr  // 列表中声明的字段名共享相同类型（相同指针）
		node
	}

	// 接口{MethodList[0]；MethodList[1]；…}
	InterfaceType struct {
		MethodList []*Field
		expr
	}

	FuncType struct {
		ParamList  []*Field
		ResultList []*Field
		expr
	}

	// map[Key]Value 
	MapType struct {
		Key, Value Expr
		expr
	}

	// chan Elem 
	// <-chan Elem 
	// /chan<-Elem 
	ChanType struct {
		Dir  ChanDir // 0表示没有方向
		Elem Expr
		expr
	}
)

type expr struct{ node }

func (*expr) aExpr() {}

type ChanDir uint

const (
	_ ChanDir = iota
	SendOnly
	RecvOnly
)

// ---------------------------------------------------------------
// Statements 

type (
	Stmt interface {
		Node
		aStmt()
	}

	SimpleStmt interface {
		Stmt
		aSimpleStmt()
	}

	EmptyStmt struct {
		simpleStmt
	}

	LabeledStmt struct {
		Label *Name
		Stmt  Stmt
		stmt
	}

	BlockStmt struct {
		List   []Stmt
		Rbrace Pos
		stmt
	}

	ExprStmt struct {
		X Expr
		simpleStmt
	}

	SendStmt struct {
		simpleStmt
	}

	DeclStmt struct {
		DeclList []Decl
		stmt
	}

	AssignStmt struct {
		Op       Operator // 0表示没有操作
		Lhs, Rhs Expr     // Rhs==nil表示Lhs++（Op==Add）或Lhs--（Op==Sub）
		simpleStmt
	}

	BranchStmt struct {
		Tok   token // Break、Continue、Fallthrough或Goto 
		Label *Name
		// Target是执行
		// 分支后控制流的继续；如果设置了checkBranchs，则由解析器计算。
		// 目标是用于gotos的*LabeledStmt，以及用于中断和继续的*SwitchStmt、*SelectStmt、
		// 或*ForStmt，具体取决于分支的
		// 上下文。没有为故障设置目标。
		Target Stmt
		stmt
	}

	CallStmt struct {
		Tok  token // Go或delay 
		Call *CallExpr
		stmt
	}

	ReturnStmt struct {
		Results Expr // nil表示没有显式返回值
		stmt
	}

	IfStmt struct {
		Init SimpleStmt
		Cond Expr
		Then *BlockStmt
		Else Stmt // nil、*IfStmt、，或*BlockStmt 
		stmt
	}

	ForStmt struct {
		Init SimpleStmt // incl.*RangeClause 
		Cond Expr
		Post SimpleStmt
		Body *BlockStmt
		stmt
	}

	SwitchStmt struct {
		Init   SimpleStmt
		Tag    Expr // incl.*TypeSwitchGuard 
		Body   []*CaseClause
		Rbrace Pos
		stmt
	}

	SelectStmt struct {
		Body   []*CommClause
		Rbrace Pos
		stmt
	}
)

type (
	RangeClause struct {
		Lhs Expr // nil表示没有Lhs=或Lhs:=
		Def bool // 表示：=
		X   Expr // 范围X 
		simpleStmt
	}

	CaseClause struct {
		Cases Expr // nil表示默认条款
		Body  []Stmt
		Colon Pos
		node
	}

	CommClause struct {
		Comm  SimpleStmt // 发送或接收stmt；NIL意味着默认条款ABCFDG ** 
		Body  []Stmt
		Colon Pos
		node
	}
)

type stmt struct{ node }

func (stmt) aStmt() {}

type simpleStmt struct {
	stmt
}

func (simpleStmt) aSimpleStmt() {}


type CommentKind uint

const (
	Above CommentKind = iota
	Below
	Left
	Right
)

type Comment struct {
	Kind CommentKind
	Text string
	Next *Comment
}
